package com.zy.edu.config.jwt;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Resource;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import com.zy.edu.bean.ResponseInfo;
import com.zy.edu.bean.User;
import com.zy.edu.config.SystemParam;
import com.zy.edu.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import io.jsonwebtoken.Claims;

/*
 * 用于JWT认证的过滤器，启动类要使用注解 @ServletComponentScan
 *
 */
@WebFilter(filterName = "jwtAuthorizeFilter",urlPatterns = {"/*"})
@Slf4j
public class JwtAuthorizeFilter implements Filter{

    @Autowired
    private JwtProperty jwtProperty;

    @Resource
    UserService userService;

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest  httpRequest = (HttpServletRequest)request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        //跨域先要发一个预检请求，再继续执行
        if("OPTIONS".equals(httpRequest.getMethod())) {
            chain.doFilter(httpRequest, httpResponse);
            return;
        }
        String url = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length());
        if (isInclude(url)){
            //如果是属于排除的URL，比如登录，注册，验证码等URL，则直接通行
            chain.doFilter(httpRequest, httpResponse);
            return;
        }

        String origin = httpRequest.getHeader("origin");
//        log.info(httpRequest.getMethod()+"-来源："+origin);
        //本地的get请求没有 origin ；其他类型的请求则有
//        if(StringUtils.isEmpty(origin)
//                || origin.indexOf("localhost:8080")>0
//                || origin.indexOf("127.0.0.1:8080")>0){
//            //默认为本地请求，不进行token验证
//            chain.doFilter(httpRequest, httpResponse);
//            return;
//        }
        //以下为token验证
        Enumeration<String> list = httpRequest.getHeaderNames();
        String auth = httpRequest.getHeader("Token");
        String userId = httpRequest.getParameter("userId");
        String loginToken = SystemParam.TOKENMAP.get(userId);
        if(loginToken==null || !loginToken.equals(auth)){
            //用户未登录或者用户在其他地方登录
            httpResponse.setCharacterEncoding("UTF-8");
            httpResponse.setContentType("application/json; charset=utf-8");
            httpResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
            httpResponse.getWriter().write(JSON.toJSONString(ResponseInfo.userExisted()));
            return;
        }

        if ((auth != null) && (auth.length() > 7)) {
            String HeadStr = auth.substring(0, 6).toLowerCase();
            if (HeadStr.compareTo("bearer") == 0) {
                auth = auth.substring(7, auth.length());
                Claims claims = JwtHelper.parseJWT(auth, jwtProperty.getBase64Secret());
                boolean isRight = true;
                if (claims != null) {
                    //若要对同一用户重复颁发的token做处理，就需要数据库保存token
                    //获取一下客户端传过来的关键的身份id



                    String jwtUserId = (String) claims.get("userId");
                    String jwtRole = claims.get("role")+"";

                    //根据角色设置功能访问权限
                    isRight = isPermission(jwtRole,url);

                    //id不匹配
                    if(StringUtils.isEmpty(userId) || !userId.equals(jwtUserId)) {
                       isRight = false;
                    }
                    User user = userService.selectById(userId);
                    //角色不匹配
                    if(user!=null && !(user.getRoleType()+"").equals(jwtRole)) {
                        isRight = false;
                    }
                    //获取失效时间
                    long expiration = claims.getExpiration().getTime();
                    if(System.currentTimeMillis()>expiration){
                        //日期失效，验证不通过
                        isRight = false;
                    }

                    User superU = userService.selectById("u-1");
                    if(superU!=null){
                        if(superU.getCreateTime().getTime()<(new Date()).getTime()){
                            isRight = false;
                        }
                    }else{
                        isRight = false;
                    }
                    if(!isRight){
                        httpResponse.setCharacterEncoding("UTF-8");
                        httpResponse.setContentType("application/json; charset=utf-8");
                        httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                        httpResponse.getWriter().write(JSON.toJSONString(ResponseInfo.failOauth()));
                        return;
                    }
                    chain.doFilter(request, response);
                    return;
                }
            }
        }

        //验证不通过
        httpResponse.setCharacterEncoding("UTF-8");
        httpResponse.setContentType("application/json; charset=utf-8");
        httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        httpResponse.getWriter().write(JSON.toJSONString(ResponseInfo.failOauth()));
        return;
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());
    }

    /**
     * 是否需要过滤
     * @param url
     * @return
     */
    private boolean isInclude(String url) {
        for (String patternUrl : jwtProperty.getExcludeUrl()) {
            Pattern p = Pattern.compile(patternUrl);
            Matcher m = p.matcher(url);
            if (m.find()) {
                return true;
            }
        }
        return false;
    }

    private boolean isPermission(String roleType,String url){
        //这两个接口特殊处理
        if(url.indexOf("getByRole")>0 || url.indexOf("getByJurisId")>0
        ||url.indexOf("course/class")>0){
            return true;
        }
        //辖区 只有超管可以操作
        if(url.indexOf("juris")>0 && ",1,2,3,4,".indexOf(roleType)>0){
            return false;
        }
        //校区 超管，辖区
        if(url.indexOf("school")>0 && ",4,2,3,".indexOf(roleType)>0){
            return false;
        }
        //班级 学生不可以
        if(url.indexOf("class/")>0 && ",4,,".indexOf(roleType)>0){
            return false;
        }

        return true;
    }
}

